package com.ws.client.utils;

import com.ws.client.other.InputSave;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.file.*;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

public class FileUtils {

    /**
     * 复制文件夹
     */
    public static void copyFile(File source, String dest) throws IOException {
        //创建目的地文件夹
        File destfile = new File(dest);
        if (!destfile.exists()) {
            destfile.mkdir();
        }
        //如果source是文件夹，则在目的地址中创建新的文件夹
        if (source.isDirectory()) {
            File file = new File(dest + "\\" + source.getName());//用目的地址加上source的文件夹名称，创建新的文件夹
            file.mkdir();
            //得到source文件夹的所有文件及目录
            File[] files = source.listFiles();
            if (files.length == 0) {
                return;
            } else {
                for (int i = 0; i < files.length; i++) {
                    if (files[i].getName().equals("LOCK")) {
                        continue;
                    }
                    copyFile(files[i], file.getPath());
                }
            }

        }
        //source是文件，则用字节输入输出流复制文件
        else if (source.isFile()) {

            FileInputStream fis = new FileInputStream(source);
            //创建新的文件，保存复制内容，文件名称与源文件名称一致
            File dfile = new File(dest + "\\" + source.getName());
            if (!dfile.exists()) {
                dfile.createNewFile();
            }

            FileOutputStream fos = new FileOutputStream(dfile);
            // 读写数据
            // 定义数组
            byte[] b = new byte[1024];
            // 定义长度
            int len;
            // 循环读取
            while ((len = fis.read(b)) != -1) {
                // 写出数据
                fos.write(b, 0, len);
            }

            //关闭资源
            fos.close();
            fis.close();

        }
    }

    /**
     * 删除前缀文件夹
     */
    public static void deleteFoldersWithPrefix(String directoryPath, String prefix) {
        File directory = new File(directoryPath);
        if (directory.isDirectory()) {
            File[] files = directory.listFiles();
            if (files != null) {
                for (File file : files) {
                    if (file.isDirectory() && file.getName().startsWith(prefix)) {
                        deleteFolder(file);
                    }
                }
            }
        }
    }

    /**
     * 获得前缀文件夹
     */
    public static List<File> getFoldersWithPrefix(String directoryPath, String prefix) {
        ArrayList<File> fileArrayList = new ArrayList<>();
        File directory = new File(directoryPath);
        if (directory.isDirectory()) {
            File[] files = directory.listFiles();
            if (files != null) {
                for (File file : files) {
                    if (file.isDirectory() && file.getName().startsWith(prefix)) {
                        fileArrayList.add(file);
                    }
                }
            }
        }
        return fileArrayList;
    }


    /**
     * 删除文件夹
     */
    public static void deleteFolder(File folder) {
        File[] files = folder.listFiles();
        if (files != null) {
            for (File file : files) {
                if (file.isDirectory()) {
                    deleteFolder(file);
                } else {
                    file.delete();
                }
            }
        }
        folder.delete();
    }


    /**
     * 创建文件夹
     */
    public static void makeDir(String path) {
        if (new File(path).mkdirs()) {
            LogHelper.debug("创建文件夹成功");
        } else {
            LogHelper.debug("创建文件夹失败");
        }
    }


    /**
     * 将文件压缩为zip并返回文件路径
     */
    public static String deZip(String sourceFolder) {
        String zipFile = sourceFolder.concat(".zip"); // 替换为生成的压缩文件路径

        try {
            FileOutputStream fos = new FileOutputStream(zipFile);
            ZipOutputStream zos = new ZipOutputStream(fos);

            File sourceDir = new File(sourceFolder);
            compressFolder(sourceDir.toPath(), sourceDir.getName(), zos);

            zos.close();
            fos.close();

            LogHelper.debug("Folder compressed successfully.");

        } catch (IOException e) {
            e.printStackTrace();
        }
        return zipFile;
    }

    /**
     * 压缩zip辅助函数
     */
    private static void compressFolder(Path folder, String parent, ZipOutputStream zos) throws IOException {
        try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(folder)) {
            for (Path file : dirStream) {
                if (Files.isDirectory(file)) {
                    // 递归压缩子文件夹
                    compressFolder(file, parent + "/" + file.getFileName(), zos);
                } else {
                    byte[] buffer = new byte[1024];
                    FileInputStream fis = new FileInputStream(file.toFile());
                    String entryName = parent + "/" + (file.getFileName().toString().isEmpty() ? "" : file.getFileName());
                    zos.putNextEntry(new ZipEntry(entryName));

                    int length;
                    while ((length = fis.read(buffer)) > 0) {
                        zos.write(buffer, 0, length);
                    }
                    fis.close();
                }
            }
        }
    }


    /**
     * 远程文件下载
     */
    public static File downloadFile(String upath) {
        File file = null;
        try {
            String downUrl = InputSave.httpHost.concat("/download?fileName=").concat(upath).concat(".zip");
            LogHelper.debug("下载文件:" + downUrl);
            // 统一资源
            URL url = new URL(downUrl);
            // 连接类的父类，抽象类
            URLConnection urlConnection = url.openConnection();
            // http的连接类
            HttpURLConnection httpURLConnection = (HttpURLConnection) urlConnection;
            // 设定请求的方法，默认是GET
            httpURLConnection.setRequestMethod("GET");
            // 设置字符编码
            httpURLConnection.setRequestProperty("Charset", "UTF-8");
            httpURLConnection.setRequestProperty("Accept-Encoding", "identity");
            // 打开到此 URL 引用的资源的通信链接（如果尚未建立这样的连接）。
            httpURLConnection.connect();
            // 文件大小
            int fileLength = httpURLConnection.getContentLength();
            LogHelper.debug("文件大小---->" + fileLength);
            // 文件名
            String filePathUrl = httpURLConnection.getURL().getFile().replace("/download?fileName=", "");
            //File.separatorChar代表的是分隔符“/”或者“\”，若详知 自行百度
            String fileFullName = filePathUrl.substring(filePathUrl.lastIndexOf(File.separatorChar) + 1);

            BufferedInputStream bin = new BufferedInputStream(httpURLConnection.getInputStream());
            String path = InputSave.cache_path + File.separatorChar + fileFullName;
            file = new File(path);
            if (!file.getParentFile().exists()) {
                file.getParentFile().mkdirs();
            }
            OutputStream out = Files.newOutputStream(file.toPath());
            int size = 0;
            int len = 0;
            byte[] buf = new byte[1024];
            while ((size = bin.read(buf)) != -1) {
                len += size;
                out.write(buf, 0, size);
                // 打印下载百分比
                System.out.print("\r" + "文件传输进度------->" + len * 100 / fileLength + "%");
            }
            bin.close();
            out.close();
            LogHelper.debug("传输已完成");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            LogHelper.debug("文件传输出现错误！！！！");
        }
        return file;
    }


    /**
     * 解压zip并返回路径
     */
    public static void unZip(String zipPath) {
        String targetFolderPath = zipPath.substring(0, zipPath.length() - 4); // 替换为目标文件夹路径
        //targetPath输出文件路径
        File targetFile = new File(targetFolderPath);
        // 如果目录不存在，则创建
        if (!targetFile.exists()) {
            targetFile.mkdirs();
        }
        //sourcePath压缩包文件路径
        try (ZipFile zipFile = new ZipFile(new File(zipPath))) {
            LogHelper.debug("总文件数:" + zipFile.size());
            Enumeration enumeration = zipFile.entries();
            while (enumeration.hasMoreElements()) {
                //依次获取压缩包内的文件实体对象
                ZipEntry entry = (ZipEntry) enumeration.nextElement();
                LogHelper.debug("文件大小:" + entry.getSize());
                String name = entry.getName();
                if (entry.isDirectory()) {
                    continue;
                }
                try (BufferedInputStream inputStream = new BufferedInputStream(zipFile.getInputStream(entry))) {
                    // 需要判断文件所在的目录是否存在，处理压缩包里面有文件夹的情况
                    String outName = targetFolderPath + "/" + name;
                    File outFile = new File(outName);
                    File tempFile = new File(outName.substring(0, outName.lastIndexOf("/")));
                    if (!tempFile.exists()) {
                        tempFile.mkdirs();
                    }
                    try (BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(outFile))) {
                        int len;
                        byte[] buffer = new byte[1024];
                        while ((len = inputStream.read(buffer)) > 0) {
                            outputStream.write(buffer, 0, len);
                        }
                    }

                }

            }

        } catch (Exception e) {
            LogHelper.debug("文件解压失败！！！！！");
            e.printStackTrace();
        }
        LogHelper.debug("文件解压完成！");
    }


    public static void uploadFileToServer(String filePath) {
        LogHelper.debug("uploadFile...");
        String serverUrl = InputSave.httpHost + "/upload";
        String paramName = "file";
        try {
            // 创建URL对象
            URL url = new URL(serverUrl);

            // 创建HttpURLConnection对象
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setDoOutput(true);
            connection.setRequestMethod("POST");
            // 设置请求头
            connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=---------------------------1234567890");

            // 创建数据输出流
            OutputStream outputStream = connection.getOutputStream();
            PrintWriter writer = new PrintWriter(new OutputStreamWriter(outputStream, "UTF-8"), true);

            // 写入参数名
            writer.append("-----------------------------1234567890\r\n");
            writer.append("Content-Disposition: form-data; name=\"").append(paramName).append("\"; filename=\"").append(new File(filePath).getName()).append("\"\r\n");
            writer.append("Content-Type: text/plain\r\n\r\n");
            writer.flush();

            // 写入文件内容
            FileInputStream fileInputStream = new FileInputStream(filePath);
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = fileInputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
            outputStream.flush();
            fileInputStream.close();

            // 写入结束符
            writer.append("\r\n");
            writer.append("-----------------------------1234567890--\r\n");
            writer.flush();
            writer.close();

            // 获取响应
            int responseCode = connection.getResponseCode();
            if (responseCode == 200) {
                LogHelper.debug("文件上传成功");
            } else {
                LogHelper.debug("文件上传失败");
            }

            // 关闭连接
            connection.disconnect();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
